package com.xtayfjpk.zookeeper.test.master_workers.recovery;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.zookeeper.ZooKeeper;

import com.xtayfjpk.zookeeper.test.master_workers.Master;
import com.xtayfjpk.zookeeper.test.master_workers.callback.recovery.AssignedWorkersCallback;
import com.xtayfjpk.zookeeper.test.master_workers.callback.recovery.GetDataReassignCallback;
import com.xtayfjpk.zookeeper.test.master_workers.callback.recovery.RecoveryTasksCallback;
import com.xtayfjpk.zookeeper.test.master_workers.callback.recovery.RecoveryWorkersCallback;
import com.xtayfjpk.zookeeper.test.master_workers.callback.recovery.TaskDeletionCallback;
import com.xtayfjpk.zookeeper.test.master_workers.callback.recovery.TaskStatusCallback;
import com.xtayfjpk.zookeeper.test.master_workers.callback.recovery.WorkerAssignmentsCallback;

public class RecoveredAssignments {
	private static final Logger LOGGER = Logger.getLogger(RecoveredAssignments.class);
	
	private List<String> taskList;
	/** 分配了但未执行完成的任务 
	 * 	如：/assign/worker-1/task-1-1
	 * **/
	private List<String> assignmentList;
	private List<String> statusList;
	/** 对应/workers下的子znode **/
	private List<String> activeWorkerList;
	/** 对应/assign下的子znode **/
	private List<String> assignedWorkerList;
	
	private Master master;
	private RecoveryCallback cb;
	private ZooKeeper zk;
	
	
	public RecoveredAssignments(ZooKeeper zk) {
		this.zk = zk;
		this.activeWorkerList = new ArrayList<>();
	}
	
	public void recover(RecoveryCallback recoveryCallback) {
		this.cb = recoveryCallback;
		getTasks();
	}

	public void getTasks() {
		zk.getChildren(
				"/tasks", 
				false, 
				new RecoveryTasksCallback(this), 
				null);	
	}
	
	public void getAssignedWorkers() {
		zk.getChildren(
				"/assign", 
				false, 
				new AssignedWorkersCallback(this), 
				null);	
	}
	
	public void getWorkers(Object ctx) {
		zk.getChildren(
				"/workers", 
				false, 
				new RecoveryWorkersCallback(this), 
				ctx);
	}
	
	/** 获取工作者已分配的任务  **/
	public void getWorkerAssignments(String path) {
		zk.getChildren(
				path, 
				false, 
				new WorkerAssignmentsCallback(this), 
				null);
	}
	
	/** 重新将未执行完成的任务添加回待执行任务列表 **/
	public void getDataReassign(String path, String task) {
		zk.getData(
				path, 
				false, 
				new GetDataReassignCallback(this), 
				task);		
	}
	
	/** 删除已经分配但未执行完成的任务 **/
	public void deleteAssignment(String path) {
		zk.delete(
				path, 
				-1, 
				new TaskDeletionCallback(this), 
				null);		
	}
	
	public void getStatuses() {
		zk.getChildren(
				"/status", 
				false, 
				new TaskStatusCallback(this), 
				null);		
	}
	
	public void processAssignments() {
		LOGGER.info("Size of tasks: " + taskList.size());
		//Process list of pending assignments
		for(String assignment : assignmentList) {
			LOGGER.info("Assignment: " + assignment);
			//任务已经重新分配，可以从待执行任务中移除
			deleteAssignment("/tasks/" + assignment);
			taskList.remove(assignment);
		}
		
		 LOGGER.info("Size of tasks after assignment filtering: " + taskList.size());
		 
		 
		 for(String status : statusList) {
			 LOGGER.info("Check task: " + status);
			 deleteAssignment("/tasks/" + status);
			 taskList.remove(status);
		 }
		 
		 LOGGER.info("Size of tasks after status filtering: " + taskList.size());
		 
		 // Invoke callback
		 cb.recoveryComplete(RecoveryCallback.OK, taskList);  
	}
	
	
	public RecoveryCallback getCb() {
		return cb;
	}

	public List<String> getTaskList() {
		return taskList;
	}

	public void setTaskList(List<String> taskList) {
		this.taskList = taskList;
	}

	public List<String> getAssignmentList() {
		if(assignmentList==null) {
			assignmentList = new ArrayList<>();
		}
		return assignmentList;
	}

	public void setAssignmentList(List<String> assignmentList) {
		this.assignmentList = assignmentList;
	}

	public List<String> getStatusList() {
		return statusList;
	}

	public void setStatusList(List<String> statusList) {
		this.statusList = statusList;
	}

	public List<String> getActiveWorkerList() {
		return activeWorkerList;
	}

	public void setActiveWorkerList(List<String> activeWorkerList) {
		this.activeWorkerList = activeWorkerList;
	}

	public List<String> getAssignedWorkerList() {
		return assignedWorkerList;
	}

	public void setAssignedWorkerList(List<String> assignedWorkerList) {
		this.assignedWorkerList = assignedWorkerList;
	}

	public void setCb(RecoveryCallback cb) {
		this.cb = cb;
	}

	public void setMaster(Master master) {
		this.master = master;
	}
	public Master getMaster() {
		return master;
	}
}
